package com.fingard.dsp.bank.directbank.scb02;

import java.io.*;
import java.util.*;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.db.JDBCHelper;
import com.fingard.dsp.bank.directbank.bankInterface.ISinglePay;
import com.fingard.dsp.bank.reqrespobj.single.*;
import com.fingard.dsp.bank.reqrespobj.single.detail.ReqPayRecDetail;
import com.fingard.dsp.bank.reqrespobj.single.detail.RetAtsSglDetail;
import com.fingard.io.FileHelper;
import com.fingard.text.Base64Helper;
import com.fingard.text.StringHelper;

/**
 * @author XueJy on 2018/8/10.
 * @version 1.0
 */
public class SCB02SinglePay extends SCB02Base implements ISinglePay {

    @Override
    public RetAtsSingle d_1908_SglPay(ReqSingle p_req1908) throws Exception {
        //创建返回对象
        RetAtsSingle retAts = new RetAtsSingle(p_req1908.reqHeader);
        //returnAts报文头
        RetAtsSglDetail respDetail = new RetAtsSglDetail();
        //获取请求详情对象
        ReqPayRecDetail reqDetail = p_req1908.singleDetail;
        //存如数据库的实体类
        List<String > askNums = new ArrayList<String>();
        boolean copyResult = false;
        try {
            StringBuilder sbPaymentBody = new StringBuilder();
        if((!"1".equals(p_req1908.singleDetail.payCur) ||! "1".equals(p_req1908.singleDetail.recCur))&&!"1".equals(p_req1908.singleDetail.sameBnk)){
            //编写请求报文体
                getBodyInTT(p_req1908,sbPaymentBody, askNums);
            }else {
                getMsgBody(p_req1908.singleDetail, sbPaymentBody, askNums, p_req1908.singleDetail.paySpd,p_req1908.reqHeader.commandCode);
          }
            //单笔付款默认一笔
            String strTotalNum = "1";
            //转账总金额
            String strTotalAmt = reqDetail.payAmount;
            //Header Record 和 Trailer Record
            String strHead = "H,P\r\n";
            String strTrail = "T" + "," + strTotalNum + "," + strTotalAmt;
            //结合报文
            StringBuilder sbPayment = new StringBuilder();
            sbPayment.append(strHead).append(sbPaymentBody.toString()).append(strTrail);
            WriteBankLogStep2(sbPayment);
            String batchCode = p_req1908.reqHeader.reqSeqID;
            //支付文件名称
            //通过配置文件读取支付文件导出路径:渣打银行client接收来自DSP发送付款文件所存放的路径
            String paymentCsvPath = getH2HPath("PaymentFilePath");
            //生成余额请求文件到备份目录的路径
            String bakDirectory = getDataFileDirectory(new Date()) + File.separator + "paymentbak";
            String bakfullName = getTrimPath(bakDirectory) + File.separator + batchCode + ".csv";
            String batchNoMappingFile = getTrimPath(bakDirectory) + File.separator + batchCode+ ".txt";

            //生成scv文件保存到指定目录
            WriteBankLogLn("生成scv文件本地备份路径" + bakfullName);
            boolean genCsvResult = writeFile(bakfullName, sbPayment.toString(), getCharset());
            StringBuilder sb = new StringBuilder();
            for (String askNum:askNums) {
                sb.append(askNum).append(",");
            }
            if (askNums.size() > 0) {
                sb.delete(sb.length() - 1, sb.length());
            }
            boolean genMapResult = writeFile(batchNoMappingFile,sb.toString(), getCharset());
            if (genCsvResult&&genMapResult) {
                //拷贝生成的支付文件到前置机目录
                copyResult = copyFile(bakfullName, paymentCsvPath);
                if (copyResult) {
                    //在一切都成功之后，将数据插入到数据库中。
                    respDetail.respCode = "0";
                    respDetail.transState = "0000";
                    respDetail.payInfoCode = "0000";
                    respDetail.respInfo = "提交成功";
                } else {
                    respDetail.respCode = "0";
                    respDetail.transState = "E1301";
                    respDetail.payInfoCode = "E1301";
                    respDetail.respInfo = "拷贝交易流水/批次号：" + batchCode + "支付请求文件发送到指定目录失败";
                }
            } else {
                respDetail.respCode = "0";
                respDetail.transState = "E1301";
                respDetail.payInfoCode = "E1301";
                respDetail.respInfo = "交易流水/批次号：" + batchCode + " 生成支付文件失败!";
            }
            retAts.writeRetDetail(respDetail);
        } catch (Exception e) {
            if (copyResult) {
                respDetail.respInfo = "提交成功,但是插入数据库失败，结果将无法查询，请联系开发人员进行解决,错误信息如下" + e.getMessage();
            } else {
                respDetail.respCode = "-1";
                respDetail.respInfo = "提交异常,错误信息如下" + e.getMessage();
                WriteBankLogLn(e);
            }
            retAts.writeRetDetail(respDetail);
        }
        return retAts;
    }

    @Override
    public RetAtsSingle d_1944_QrySglPay(ReqQrySingle p_req1944) throws Exception {
        RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);
        //初始化返回信息
        retAts.retHeader.bankCode = p_req1944.reqHeader.bankCode;
        retAts.retHeader.transType = p_req1944.reqHeader.transType;
        retAts.retHeader.transSeqID = p_req1944.reqHeader.transSeqID;

        RetAtsSglDetail retDetail = new RetAtsSglDetail();

        //返回详情
        String batchNo = p_req1944.askNumber;
        retDetail.reqSeqID = batchNo;
        //计算日期，如果日期大于指定日期区间，则不允许查询, 在允许的情况下，获取一个日期的集合，用来排查文件夹名。
        Calendar calNow = Calendar.getInstance();
        calNow.setTime(new Date());
        Calendar calBgn = Calendar.getInstance();
        calBgn.setTime(p_req1944.getBgnDateTime());
        //获取天数差
        int days = calNow.get(Calendar.DAY_OF_YEAR) - calBgn.get(Calendar.DAY_OF_YEAR);
        String queryResultDateSpan = getBankConfig().getMapValueByKey("params", "QueryResultDateSpan");
        //判断 请求的的日期是否满足要求
        if (queryResultDateSpan != null && !"".equals(queryResultDateSpan)) {
            if (days > Integer.parseInt(queryResultDateSpan) || days < 0) {
                retDetail.respCode = "-1";
                if (days < 0) {
                    retDetail.respInfo = "单据发送日期超出查询日期";
                } else {
                    retDetail.respInfo = "单据发送日期与查询日期相隔时间太长,时间间隔规定小于" + Integer.parseInt(queryResultDateSpan);
                }
                retAts.writeRetDetail(retDetail);
                return retAts;
                //日期超限了。。不能查询
            }
        }
        List<Date> dateBufer = new ArrayList<Date>();
        dateBufer.add(calNow.getTime());
        for (int i = 0; i <= days; i++) {
        	calNow.add(calNow.DAY_OF_YEAR, -1);
            dateBufer.add(calNow.getTime());
        }
        //排序
        // 第一步，先下载（复制）所有文件到本地目录（带日期的），下载完毕之后还要删除原来的文件
        try {
            scb02Download();
        } catch (Exception e) {
            retDetail.respCode = "-1";
            retDetail.respInfo = "下载（复制）文件到本地目录失败";
            retAts.writeRetDetail(retDetail);
            WriteBankLogLn(e);
            return retAts;
        }
        // 第二步，先判断是不是整批失败？
        StringBuilder eorryCode = new StringBuilder();
        StringBuilder eorryMessage = new StringBuilder();
        String respType = "";
        //tmpReqSeqID:流水号批次号
        String payFlieName = batchNo + ".csv";
        String ack3Path = getH2HPath("PayReturnACK3byWINTER");
        String toPath2 = "";
        for (Date datePathDate : dateBufer) {
            //yyyyMMdd
            String datePath = Format.Date8Format.format(datePathDate);
            //如果整批失败，就OUT 错误信息。
            //获取支付状态响应类型
            toPath2 = getTrimPath(ack3Path) + File.separator + datePath.substring(0, 6) + File.separator + datePath.substring(6, 8);
            respType = getPaymentStatusResponseType(toPath2, payFlieName);
            if (StringHelper.isNullOrEmpty(respType)) {
                String rej3Path = getH2HPath("PayReturnREJ3byWINTER");
                String toPath3 = getTrimPath(rej3Path) + File.separator + datePath.substring(0, 6) + File.separator + datePath.substring(6, 8);
                respType = getPaymentStatusResponseTypeREJ3(toPath3, payFlieName, eorryCode, eorryMessage);
                if (respType != null && !"".equals(respType)) {
                    retDetail.respInfo = eorryMessage.toString();
                    retDetail.transState = respType + "+" + eorryCode.toString();
                    retDetail.payInfoCode = eorryCode.toString();
                    retAts.writeRetDetail(retDetail);
                    return retAts;
                    //如果找到了值，那么就直接跳出循环，返回结果了，并且整批失败；
                }
            } else {
                break;
            }
        }
        //跳出循环后

        // 第三步，先找出，需要查询的流水号
        String bakDirectory = getDataFileDirectory( p_req1944.getBgnDateTime()) + File.separator + "paymentbak";
        String batchNoMappingFile = getTrimPath(bakDirectory) + File.separator + batchNo+ ".txt";
        String content = FileHelper.readFileText(batchNoMappingFile, getCharset());
        if ("".equals(content) || content == null) {
            //支付中
            retDetail.respCode = "-1";
            retDetail.respInfo = batchNoMappingFile + "中未找到批次号，请联系技术人员";
            retAts.writeRetDetail(retDetail);
            return retAts;
        }
        List<String> dtpostscripts = new ArrayList<String>(Arrays.asList(content.split(",")));

        // 第四步，创建循环体，找出一批当中所有的批次后开始循环赋值
        //第一层 要查找的流水号总过数量循环
        // 拨玉米皮，开始检索
        //第二层，日期文件夹

        //  Hashtable htable = new Hashtable();
        RetAtsSglDetail detail1944 = paypocForTT(dateBufer, retDetail, dtpostscripts);
        if (detail1944 == null) {
            retDetail.respCode = "0";
            retDetail.respInfo = "还未查到相关流水号的数据，对方还未返回结果";
            //支付中
            retDetail.transState = "4";
            retDetail.payInfoCode = "";
            retAts.writeRetDetail(retDetail);
            return retAts;
        } else {
            retDetail.respCode = "0";
            retDetail.respInfo = "查询成功";
            retAts.writeRetDetail(detail1944);
            return retAts;
        }

    }

    @Override
    public RetAtsSingleBat d_1908BAT_SglBatPay(ReqSingleBat p_req1908BAT) throws Exception {
        return null;
    }

    @Override
    public RetAtsSingleBat d_1944BAT_QrySglBatPay(ReqQrySingleBat p_req1944BAT) throws Exception {
        return null;
    }

    private void getBodyInTT(ReqSingle p_req1908 ,StringBuilder sbPaymentBody, List<String> askNumMap) throws Exception {
        ReqPayRecDetail reqDetail = p_req1908.singleDetail;
        //一共63个  最后个E 为了splite出所有中间的空字符
        String strPayment = "P,TT,ON,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,E";
        //166字段需要填写pop
//        String strPayment = "P,TT,ON,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,E";
        String[] sPaymentItems = strPayment.split(",");
        //对账码
        sPaymentItems[4] = reqDetail.askNumber;
        //备注-->不支持中文
        if (reqDetail.memo != null && !pattern.matcher(reqDetail.memo).find()) {
            sPaymentItems[5] = hasCommaAddDoubleQuotes(reqDetail.memo);
        }
        //付款账户所属国家
        sPaymentItems[6] = reqDetail.payCountryCode;
        //付款账户所属国家城市 Payment Supplementary --- Debit Bank Payment Information
        sPaymentItems[7] = getBankConfig().getMapValueByKey("cityCode", sPaymentItems[6]);
        //付款账户
        sPaymentItems[8] = reqDetail.payAct;
        //PayDate
        Date payDate = Format.Date10Format.parse(reqDetail.payDate);
        sPaymentItems[9] = sdf.format(payDate);

        //收款人姓名  如果有中文需要Base64放到50,51
        String enName = getBankConfig().getMapValueByKey("BTnameMapping", reqDetail.recAct);
        if (enName != null &&!"".equals(enName)) {
            reqDetail.recName = enName;
        }

        recNameFormat(sPaymentItems, reqDetail.recName);

        //Swift BIC
        sPaymentItems[15] = reqDetail.recSwiftCode;
        //收款人账号
        sPaymentItems[19] = reqDetail.recAct;
        //English Payee Bank reqDetail 收款银行名称明细???
        if (reqDetail.recBankInEng != null && !"".equals(reqDetail.recBankInEng)) {
            reqDetail.cnapsName = reqDetail.recBankInEng;
        } else {
            String recBankNm = getBankConfig().getMapValueByKey("TTRecBankNm", reqDetail.cnapsName);
            if (recBankNm != null &&!"".equals(recBankNm)) {
                reqDetail.cnapsName = recBankNm;
            }
        }
            if (reqDetail.cnapsName != null && !pattern.matcher(reqDetail.cnapsName).find()) {
                sPaymentItems[20] = reqDetail.cnapsName;
             }
             recBnkNmFormat(sPaymentItems, reqDetail.cnapsName);
              //English Payment reqDetail
            if (reqDetail.purpose != null && !pattern.matcher(reqDetail.purpose).find()) {
                sPaymentItems[21] = reqDetail.purpose;
            }
            String memo ="+"+ reqDetail.abstractATS + "+" + reqDetail.purpose;
            memoFormat(sPaymentItems, memo);
        //57要求转换成BASE64   长度小于70
        //付款币种
        sPaymentItems[37] = convertCurToBank(reqDetail.recCur);
        //付款金额 Invoice Amount  (9(12).9(2))
        sPaymentItems[38] = hasCommaAddDoubleQuotes(reqDetail.payAmount);
        //手续费承担方
        String costMode = reqDetail.feePayer;
        //默认OUR 承担
        costMode = "SHA".equals(costMode) ? "S" : "BEN".equals(costMode) ? "P" : "OUR".equals(costMode) ? "C" : "C";
          //C for payor P for payee  本地手续费
          sPaymentItems[39] = costMode;
        //C for payor P for payee  境外手续费
        sPaymentItems[40] = costMode;
        //税率类型 S-System Rate C-Contract Rate  H-Held Rate
        sPaymentItems[48] = "S";
        //合并字段
        StringBuilder strLine = new StringBuilder();
        for (String strTemp : sPaymentItems) {
            strLine.append(strTemp).append(",");
        }
        //删除最后额外的三个字符 (,E , )
        strLine.delete(strLine.length() - 3, strLine.length());
        strLine.append("\r\n");
        // 1、Record Type                                               R-Regulatory
        // 2、Oversea/Domestic Payment                       O/D
        // 3、Unit Code                                                   付款组织机构代码    按国家质量监督检疫总局颁发的组织机构代码证或外汇局签发的特殊机构赋码通知书上的单位组织机构代码或特殊机构代码填写
        // 4、Resident Country / Region Name & Code   收方区域代码           344/香港
        // 5、Payment uder bonded goods?                    Y/N
        // 6、Payment Term                                            A=预付货款 P=货到付款 R=退款  O=其他
        // 7、Nature of Payment                                     境内付款需填写
        // 8、BOP Transaction code1                              涉外收支代码 321000 职工报酬(工资、薪金和福利)、投资收益、直接投资股息,红利
        // 9、BOP Transaction code2
        // 10、Currency1                                                 支付币种
        // 11、Amount1                                                   支付 金额
        // 12、Currency2
        // 13、Amount2
        // 14、Transaction Remark1                                Payroll  Base64
        // 15、Transaction Remark2
        // 16、Contract No
        // 17、Invoice No
        // 18、Safe Approval/Fillilng No
        //默认境外汇款第二个字段为O
        String strRegulatory = "R,O,,,,,,,,,,,,,,,,,E";
        String[] sRegulatoryItems = strRegulatory.split(",");
        // Unitcode  组织机构代码
        sRegulatoryItems[2] = reqDetail.payOrgCode;
        //  收方区域/国家代码
        sRegulatoryItems[3] = reqDetail.recCountry;
        //Bonded goods?       Y/N
        sRegulatoryItems[4] = reqDetail.isBondedGood;
        // Payment Term       A=预付货款 P=货到付款 R=退款  O=其他
        sRegulatoryItems[5] = reqDetail.payMethod;
        //BOP Transaction code1     321000 职工报酬(工资、薪金和福利)、投资收益、直接投资股息,红利
        sRegulatoryItems[7] = reqDetail.transCode1;
        //Currency币种1  监管信息币种
        sRegulatoryItems[9] =convertCurToBank(reqDetail.currency1) ;
        //amount1收付金额1
        sRegulatoryItems[10] = reqDetail.amount1;
        //Transaction Remark 交易备注1
        sRegulatoryItems[13] = Base64Helper.getBase64(reqDetail.transRemark1, "GBK");
        //BOP Transaction code1     321000 职工报酬(工资、薪金和福利)、投资收益、直接投资股息,红利

        if (reqDetail.transCode2 != null && !"".equals(reqDetail.transCode2)) {
            sRegulatoryItems[8] = reqDetail.transCode2;
        }
        //Currency币种2  监管信息币种
        if (reqDetail.currency2 != null && !"".equals(reqDetail.currency2)) {
            sRegulatoryItems[11] = convertCurToBank(reqDetail.currency2);
        }
        //Currency币种2  监管信息币种
        if (reqDetail.amount2 != null && !"".equals(reqDetail.amount2)) {
            sRegulatoryItems[12] = reqDetail.amount2;
        }
        //Transaction Remark 交易备注2
        if (reqDetail.transRemark2 != null && !"".equals(reqDetail.transRemark2)) {
            sRegulatoryItems[14] = Base64Helper.getBase64(reqDetail.transRemark2, "GBK");
        }
        if (reqDetail.contractNo != null && !"".equals(reqDetail.contractNo)) {
            sRegulatoryItems[15] =Base64Helper.getBase64(reqDetail.contractNo,"GBK");
        }
        if (reqDetail.invoiceNo != null && !"".equals(reqDetail.invoiceNo)) {
            sRegulatoryItems[16] =Base64Helper.getBase64(reqDetail.invoiceNo,"GBK");
        }
        if (reqDetail.safeOrFillingNo != null && !"".equals(reqDetail.safeOrFillingNo)) {
            sRegulatoryItems[17] =Base64Helper.getBase64(reqDetail.safeOrFillingNo,"GBK");
        }



        //合并字段
        for (String strTemp : sRegulatoryItems) {
            strLine.append(strTemp).append(",");
        }
        //删除最后额外的三个字符 (,E , )
        strLine.delete(strLine.length() - 3, strLine.length());
        strLine.append("\r\n");
        //返回strBody
        sbPaymentBody.append(strLine.toString());
        askNumMap.add(sPaymentItems[4]);
    }

    RetAtsSglDetail paypocForTT(List<Date> dateBuffer, RetAtsSglDetail retDetail, List<String> dtpostscripts) throws Exception {

        String sLine;
        for (Date datePathDate : dateBuffer) {
            String datePath = Format.Date8Format.format(datePathDate);
            //最�K�Y果RPT文件
            String rptPath = getH2HPath("PayReturnRPTbyWINTER");
            String toPath = getTrimPath(rptPath) + File.separator + datePath.substring(0, 6) + File.separator + datePath.substring(6, 8);
            WriteBankLogLn("遍历结果文件目录：" + toPath.toString());

            if (StringHelper.isNullOrEmpty(toPath)) {
                WriteBankLogLn("支付状态文件路径为空!");
            }
            //确认文件夹是存在的
            File toPathFile = new File(toPath);
            if (!toPathFile.exists()) {
                continue;
            }
            //获取路径下的所有文件名
            List<String> filenamelist = getDirChildNameByDate(toPath);
            if (filenamelist != null && filenamelist.size() > 0) {
                //第三层，文件夹下的文件列表
                for (String filename : filenamelist) {
                    //读取每一个文件
                    //文件路径
                    String fullName = getTrimPath(toPath) + File.separator + filename;
                    synchronized (this) {
                        //读取支付状态类型文件
                        //循环读取里面的内容，并且将内容进行查找，找到自己想要的那一笔数据。
                        InputStream inputStream = new FileInputStream(fullName);
                        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, getCharset()));
                        while ((sLine = reader.readLine()) != null) {
                            if (!"".equals(sLine)) {
                                for (String postscript : dtpostscripts) {
                                    if (sLine.indexOf(postscript) >= 1) {
                                        WriteBankLogStep3(sLine);
                                        //"H","SCBLMYKXXXX","GROUPID1","161128","1229","28112016123535","Transaction Status Report","MY","","","","","","","","","","","","","","","",""
                                        //"D","8059378351269","F3","Accepted","D0000042","R0000064","20161128","20161124","",1400000.00,"MYR","MYR","MYR",0.000000,"","","","","500000000001","XXXXXXXXX TELCO INFRA XXX XXX","XXXXXXXXX TELCO INFRA XXX XXX","NO 00 XXXXX XXXXXXX XXX 0/0","XXXXXX BUSINESS PARK","/MALAYSIA","","","","","","012345678900","RTGS","","SCUISTS1R0000064","",""
                                        //"D","8059378351270","F2","Rejected","D0000070","R0000102","20161128","20161124","",20000.00,"MYR","MYR","MYR",0.000000,"","<88> Duplicate CR [1500000098161000]","","","200000000000002","XXXXXX XXXXXX XXX XXX-NEW4","XXXXXX XXXXXX XXX XXX-NEW4","00-00, 00 BUSINESS PARK 0","XXXXX XXXXXXX","/MALAYSIA","","","","","","012345678900","BT","","SCUISTS1R0000102","",""
                                        //"D","1500000098161000","F3","Accepted","D0000067","R0000099","20161128","20161124","",3000.00,"MYR","MYR","MYR",0.000000,"","","","","100000000008","XXX SCIENCE AND TECHNOLOGIES CORP.","XXX SCIENCE AND TECHNOLOGIES CORP.","XXXXXXX XX XXXXXXX XXXXXXX CENTER 0","XXXXXXX DISTRICT","/CHINA","","","","","","012345678900","TT","","SCUISTS1R0000099","",""
                                        //"T",3
                                        //D2 Customer reference 客户参考号
                                        String[] sLines = sLine.split(",");
                                        //把字符串的双引号都去掉
                                        retDetail.transAmt = sLines[9].replace("\"", "");
                                        //Valid values are
                                        //F1 - Processed
                                        //F2 - Rejected
                                        //F3 - Received in Bank
                                        //F4 - Cheque cleared.
                                        //F5 �C Cheque Stopped
                                        //F6 �C Stale Cheque
                                        retDetail.transState = sLines[2].replace("\"", "").trim();
                                        retDetail.payInfoCode = sLines[2].replace("\"", "").trim() + "+" + sLines[3].replace("\"", "");
                                        //结果状态描述
                                        retDetail.respInfo = sLines[15].replace("\"", "");
                                        reader.close();
                                        inputStream.close();
                                        return retDetail;
                                    }
                                }
                            }
                        }
                        reader.close();
                        inputStream.close();
                    }
                }
            }
        }
        return null;
    }


}
